#include <iostream>
#include <string>
#include <unordered_map>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <strings.h>

const int size = 1024;

void Tip()
{
    std::cout << "./client ip port" << std::endl;
}

struct ThreadData
{
    struct sockaddr_in sock;
    int sockfd;
    // std::string clientip;
};

void* Recv(void* arg)
{
    struct ThreadData* td = static_cast<struct ThreadData*>(arg);

    while(1)
    {
        char inbuffer[size];
        struct sockaddr_in serversock;
        socklen_t socklen = sizeof(serversock);
        ssize_t n = recvfrom(td->sockfd, inbuffer, sizeof(inbuffer)-1, 0, (struct sockaddr*)&serversock, &socklen);
        if(n > 0)
        {
            inbuffer[n] = 0;
            std::cerr << inbuffer << std::endl;
        }
    }
}

void* Send(void* arg)
{
    struct ThreadData* td = static_cast<struct ThreadData*>(arg);

    socklen_t len = sizeof(td->sock);
    while(1)
    {
        std::cout << "client enter#";
        std::string outbuffer;
        std::getline(std::cin, outbuffer);
        sendto(td->sockfd, outbuffer.c_str(), outbuffer.size(), 0, (const struct sockaddr*)&(td->sock), len);
    }
}

int main(int argc, char* argv[]) //./client ip port
{
    if(argc != 3)
    {
        Tip();
        exit(0);
    }
    char* clientip = argv[1];
    uint16_t clientport = std::stoi(argv[2]);

    struct ThreadData td;
    bzero(&td.sock, sizeof(td.sock));
    td.sock.sin_family = AF_INET;
    td.sock.sin_port = htons(clientport);
    td.sock.sin_addr.s_addr = inet_addr(clientip);
    td.sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    // td.clientip = clientip;

    pthread_t recv, send;
    pthread_create(&recv, nullptr, Recv, (void*)&td);
    pthread_create(&send, nullptr, Send, (void*)&td);

    pthread_join(recv, nullptr);
    pthread_join(send, nullptr);

    close(td.sockfd);

    return 0;
}